﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Windows.Data;
using System.Windows.Interactivity;
using HugeFlow.Utility;
using HugeFlow.CommandPattern.Commands;

namespace HugeFlow.CommandPattern.Interactivity
{ 
    /// <summary>
    /// CommandName을 가진 ViewModel을 찾아 Command InstantCommand을 바인딩 해줍니다. 
    /// </summary>
    public class ExecuteAncestorInstantCommandBehavior : ExecuteCommandBehaviorBase
    {
        #region Properties

        [Category("Command")]
        public string CommandName { get; set; }

        InstantCommandBinder _triggers = new InstantCommandBinder();
        public override ICommand CommandTriggers { get { return _triggers; } }

        #endregion Properties

        #region Methods

        protected override void OnAttached()
        {
            base.OnAttached();

            if (CommandName == null)
                throw new NullReferenceException(CommandPatternResource.NullCommand);

            AssociatedObject.Loaded += new RoutedEventHandler(AssociatedObject_Loaded);
        }     

        protected override void OnDetaching()
        {
            _triggers.ClearValue(FrameworkElement.DataContextProperty);
            _triggers.ClearValue(InstantCommandBinder.InstantCommandProperty);
            _triggers.ClearValue(CommandBinderBase.InstantCommandParameterProperty);

            base.OnDetaching();
        }

        #endregion Methods

        #region EventHandlers

        void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
        {
            AssociatedObject.Loaded -= new RoutedEventHandler(AssociatedObject_Loaded);

            if (CommandParameter != null)
            {
                _triggers.SetBinding(CommandBinderBase.InstantCommandParameterProperty, GetProperBinding(_triggers, CommandParameter));
            }

            FrameworkElement parent = AssociatedObject as FrameworkElement;
            while (parent != null)
            {
                if (parent.DataContext != null)
                {
                    if (parent.DataContext.GetType().GetProperty(CommandName, typeof(InstantCommand<object>)) != null)
                    {
                        Binding binding = new Binding(CommandName);
                        binding.Source = parent.DataContext;
                        _triggers.SetBinding(InstantCommandBinder.InstantCommandProperty, binding);

                        if (_triggers.InstantCommand != null)
                            return;
                    }
                }

                parent = VisualTreeHelper.GetParent(parent) as FrameworkElement;
            }

            OnDetaching();
        }

        #endregion EventHandlers

    }
}
